/*
 *	WARN  :  THIS FRONTEND CODE IS AUTO GENERATE, ALL RIGHTS RESERVED.
 *	AUTHOR:  ZhaoChunPing
 *	EMAIL :  forxy@126.com
 *	DATE  :  2022.1
 */

#include <stdint.h>
#include "pkcs11.h"
#include "session.h"
#include "msg_fmt.h"
#include "auto_cmd.h"

CK_RV	C_LoginUser
(
	CK_SESSION_HANDLE hSession,
	CK_USER_TYPE userType,
	CK_UTF8CHAR_PTR pPin,
	CK_ULONG ulPinLen,
	CK_UTF8CHAR_PTR pUsername,
	CK_ULONG ulUsernameLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_LoginUser);
	CK_USER_TYPE_pack(userType, &p);
	DATA_pack(pPin, ulPinLen, &p);
	DATA_pack(pUsername, ulUsernameLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_Logout
(
	CK_SESSION_HANDLE hSession
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_Logout);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_EncryptInit
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism,
	CK_OBJECT_HANDLE hKey
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_EncryptInit);
	CK_MECHANISM_pack(pMechanism, &p);
	CK_OBJECT_HANDLE_pack(hKey, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_EncryptUpdate
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pPart,
	CK_ULONG ulPartLen,
	CK_BYTE_PTR pEncryptedPart,
	CK_ULONG_PTR pulEncryptedPartLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_EncryptUpdate);
	DATA_pack(pPart, ulPartLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pEncryptedPart, pulEncryptedPartLen);
	return CKR_OK;
}

CK_RV	C_EncryptFinal
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pLastEncryptedPart,
	CK_ULONG_PTR pulLastEncryptedPartLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_EncryptFinal);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pLastEncryptedPart, pulLastEncryptedPartLen);
	return CKR_OK;
}

CK_RV	C_Encrypt
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pData,
	CK_ULONG ulDataLen,
	CK_BYTE_PTR pEncryptedData,
	CK_ULONG_PTR pulEncryptedDataLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_Encrypt);
	DATA_pack(pData, ulDataLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pEncryptedData, pulEncryptedDataLen);
	return CKR_OK;
}

CK_RV	C_DecryptInit
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism,
	CK_OBJECT_HANDLE hKey
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DecryptInit);
	CK_MECHANISM_pack(pMechanism, &p);
	CK_OBJECT_HANDLE_pack(hKey, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_DecryptUpdate
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pEncryptedPart,
	CK_ULONG ulEncryptedPartLen,
	CK_BYTE_PTR pPart,
	CK_ULONG_PTR pulPartLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DecryptUpdate);
	DATA_pack(pEncryptedPart, ulEncryptedPartLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pPart, pulPartLen);
	return CKR_OK;
}

CK_RV	C_DecryptFinal
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pLastPart,
	CK_ULONG_PTR pulLastPartLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DecryptFinal);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pLastPart, pulLastPartLen);
	return CKR_OK;
}

CK_RV	C_Decrypt
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pEncryptedData,
	CK_ULONG ulEncryptedDataLen,
	CK_BYTE_PTR pData,
	CK_ULONG_PTR pulDataLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_Decrypt);
	DATA_pack(pEncryptedData, ulEncryptedDataLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pData, pulDataLen);
	return CKR_OK;
}

CK_RV	C_DigestInit
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DigestInit);
	CK_MECHANISM_pack(pMechanism, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_DigestUpdate
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pPart,
	CK_ULONG ulPartLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DigestUpdate);
	DATA_pack(pPart, ulPartLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_DigestFinal
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pDigest,
	CK_ULONG_PTR pulDigestLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DigestFinal);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pDigest, pulDigestLen);
	return CKR_OK;
}

CK_RV	C_Digest
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pData,
	CK_ULONG ulDataLen,
	CK_BYTE_PTR pDigest,
	CK_ULONG_PTR pulDigestLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_Digest);
	DATA_pack(pData, ulDataLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pDigest, pulDigestLen);
	return CKR_OK;
}

CK_RV	C_Sign
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pData,
	CK_ULONG ulDataLen,
	CK_BYTE_PTR pSignature,
	CK_ULONG_PTR pulSignatureLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_Sign);
	DATA_pack(pData, ulDataLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pSignature, pulSignatureLen);
	return CKR_OK;
}

CK_RV	C_Verify
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pData,
	CK_ULONG ulDataLen,
	CK_BYTE_PTR pSignature,
	CK_ULONG ulSignatureLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_Verify);
	DATA_pack(pData, ulDataLen, &p);
	DATA_pack(pSignature, ulSignatureLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_GenerateRandom
(
	CK_SESSION_HANDLE hSession,
	CK_BYTE_PTR pRandomData,
	CK_ULONG ulRandomLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_GenerateRandom);
	CK_ULONG_pack(ulRandomLen, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack2(&p, pRandomData, ulRandomLen);
	return CKR_OK;
}

CK_RV	C_GenerateKey
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism,
	CK_ATTRIBUTE_PTR pTemplate,
	CK_ULONG ulCount,
	CK_OBJECT_HANDLE_PTR phKey
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_GenerateKey);
	CK_MECHANISM_pack(pMechanism, &p);

	ARRAY_SIZE_pack(ulCount, &p);
	for(i = 0; i < ulCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	CK_OBJECT_HANDLE_unpack(&p, phKey);
	return CKR_OK;
}

CK_RV	C_GenerateKeyPair
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism,
	CK_ATTRIBUTE_PTR pPublicKeyTemplate,
	CK_ULONG ulPublicKeyAttributeCount,
	CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
	CK_ULONG ulPrivateKeyAttributeCount,
	CK_OBJECT_HANDLE_PTR phPublicKey,
	CK_OBJECT_HANDLE_PTR phPrivateKey
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_GenerateKeyPair);
	CK_MECHANISM_pack(pMechanism, &p);

	ARRAY_SIZE_pack(ulPublicKeyAttributeCount, &p);
	for(i = 0; i < ulPublicKeyAttributeCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pPublicKeyTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	ARRAY_SIZE_pack(ulPrivateKeyAttributeCount, &p);
	for(i = 0; i < ulPrivateKeyAttributeCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pPrivateKeyTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	CK_OBJECT_HANDLE_unpack(&p, phPublicKey);
	CK_OBJECT_HANDLE_unpack(&p, phPrivateKey);
	return CKR_OK;
}

CK_RV	C_CreateObject
(
	CK_SESSION_HANDLE hSession,
	CK_ATTRIBUTE_PTR pTemplate,
	CK_ULONG ulCount,
	CK_OBJECT_HANDLE_PTR phObject
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_CreateObject);

	ARRAY_SIZE_pack(ulCount, &p);
	for(i = 0; i < ulCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	CK_OBJECT_HANDLE_unpack(&p, phObject);
	return CKR_OK;
}

CK_RV	C_DestroyObject
(
	CK_SESSION_HANDLE hSession,
	CK_OBJECT_HANDLE hObject
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_DestroyObject);
	CK_OBJECT_HANDLE_pack(hObject, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_FindObjectsInit
(
	CK_SESSION_HANDLE hSession,
	CK_ATTRIBUTE_PTR pTemplate,
	CK_ULONG ulCount
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_FindObjectsInit);

	ARRAY_SIZE_pack(ulCount, &p);
	for(i = 0; i < ulCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_FindObjects
(
	CK_SESSION_HANDLE hSession,
	CK_ULONG ulMaxObjectCount,
	CK_OBJECT_HANDLE_PTR phObject,
	CK_ULONG_PTR pulObjectCount
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_FindObjects);
	CK_ULONG_pack(ulMaxObjectCount, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	CK_OBJECT_HANDLE_ARRAY_unpack(&p, phObject, pulObjectCount);
	return CKR_OK;
}

CK_RV	C_FindObjectsFinal
(
	CK_SESSION_HANDLE hSession
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_FindObjectsFinal);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_GetAttributeValue
(
	CK_SESSION_HANDLE hSession,
	CK_OBJECT_HANDLE hObject,
	CK_ATTRIBUTE_PTR pTemplate,
	CK_ULONG ulCount
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_GetAttributeValue);
	CK_OBJECT_HANDLE_pack(hObject, &p);

	ARRAY_SIZE_pack(ulCount, &p);
	for(i = 0; i < ulCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	CK_ATTRIBUTE_ARRAY_unpack(&p, pTemplate, ulCount);
	return CKR_OK;
}

CK_RV	C_SetAttributeValue
(
	CK_SESSION_HANDLE hSession,
	CK_OBJECT_HANDLE hObject,
	CK_ATTRIBUTE_PTR pTemplate,
	CK_ULONG ulCount
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_SetAttributeValue);
	CK_OBJECT_HANDLE_pack(hObject, &p);

	ARRAY_SIZE_pack(ulCount, &p);
	for(i = 0; i < ulCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	return CKR_OK;
}

CK_RV	C_WrapKey
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism,
	CK_OBJECT_HANDLE hWrappingKey,
	CK_OBJECT_HANDLE hKey,
	CK_BYTE_PTR pWrappedKey,
	CK_ULONG_PTR pulWrappedKeyLen
)
{
	int      ret, len, sz;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_WrapKey);
	CK_MECHANISM_pack(pMechanism, &p);
	CK_OBJECT_HANDLE_pack(hWrappingKey, &p);
	CK_OBJECT_HANDLE_pack(hKey, &p);

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	DATA_unpack_copy(&p, pWrappedKey, pulWrappedKeyLen);
	return CKR_OK;
}

CK_RV	C_UnwrapKey
(
	CK_SESSION_HANDLE hSession,
	CK_MECHANISM_PTR pMechanism,
	CK_OBJECT_HANDLE hUnwrappingKey,
	CK_BYTE_PTR pWrappedKey,
	CK_ULONG ulWrappedKeyLen,
	CK_ATTRIBUTE_PTR pTemplate,
	CK_ULONG ulAttributeCount,
	CK_OBJECT_HANDLE_PTR phKey
)
{
	int      ret, len, sz, i;
	uint8_t  *p, *rbf, *wbf;
	uint32_t result;

	sz  = MSG_RECV_BUFFER_SIZE(hSession);
	wbf = MSG_SEND_BUFFER_START(hSession);
	rbf = MSG_RECV_BUFFER_START(hSession);

	MSG_ENCODE_INIT(wbf, &p, CMD_C_UnwrapKey);
	CK_MECHANISM_pack(pMechanism, &p);
	CK_OBJECT_HANDLE_pack(hUnwrappingKey, &p);
	DATA_pack(pWrappedKey, ulWrappedKeyLen, &p);

	ARRAY_SIZE_pack(ulAttributeCount, &p);
	for(i = 0; i < ulAttributeCount; i++)
	{
		CK_ATTRIBUTE_PTR one = pTemplate + i;
		CK_ATTRIBUTE_pack(one, &p);
	}

	len = p - wbf - 2;
	*(uint16_t *)wbf = htons(len);

	/* send msg */
	ret = session_send(hSession, wbf, len + 2);
	if(ret <= 0) {
		 return CKR_CHAN_WRITE;
	}
	/* recv msg */
	ret = session_recv(hSession, rbf, sz);
	if(ret <= 0) {
		 return CKR_CHAN_READ;
	}

	/* decode */
	MSG_DECODE_INIT(rbf, &p, &result);
	if(result != CKR_OK) {
		return result;
	}
	CK_OBJECT_HANDLE_unpack(&p, phKey);
	return CKR_OK;
}

